"""
时间格式转换
"""

import copy
import re

from dateutil.relativedelta import relativedelta

from config import settings
from my_typing import *


class TimeConverter:
    """ 时间转换器 """

    @staticmethod
    def date_2_datetime(
        date_param: DateOrStr,
        to_string: bool = False,
    ) -> DateTimeOrStr:
        """
        日期/日期字符串 -> 日期时间/日期时间字符串

        Args:
            date_param: 日期/日期字符串
            to_string: 是否转换为字符串

        Returns:
            日期时间/日期时间字符串

        Examples:
            >>> TimeConverter.date_2_datetime("2024-02-06")
            datetime(2024, 2, 6)

            >>> TimeConverter.date_2_datetime("2024-02-06", to_string=True)
            "2024-02-06 00:00:00"

            >>> TimeConverter.date_2_datetime(date(2024, 2, 6))
            datetime(2024, 2, 6)

            >>> TimeConverter.date_2_datetime(date(2024, 2, 6), to_string=True)
            "2024-02-06 00:00:00"
        """

        if isinstance(date_param, date):
            date_string = str(date_param)[0:10]

        else:
            date_string = str(date_param)

        datetime_result: datetime = datetime.strptime(date_string, settings.FORMAT.DATE_FORMAT)

        if to_string:
            return datetime_result.strftime(settings.FORMAT.DATETIME_FORMAT)

        return datetime_result

    @staticmethod
    def date_2_date_str(date_param: DateOrStr) -> str:
        """
        日期/日期字符串 -> 日期字符串

        Args:
            date_param: 日期/日期字符串

        Returns:
            日期字符串

        Examples:
            >>> TimeConverter.date_2_date_str(date(2024, 2, 6))
            "2024-02-06"

            >>> TimeConverter.date_2_date_str("2024-02-06")
            "2024-02-06"
        """

        if isinstance(date_param, date):
            date_string = str(date_param)[0:10]

        else:
            date_string = str(date_param)

        date_result: date = TimeConverter.date_str_2_date(date_string)
        date_result_string: str = date_result.strftime(settings.FORMAT.DATE_FORMAT)

        return date_result_string

    @staticmethod
    def date_str_2_date(date_param: DateOrStr) -> date:
        """
        日期/日期字符串 -> 日期

        Args:
            date_param: 日期字符串

        Returns:
            日期

        Examples:
            >>> TimeConverter.date_2_date_str("2024-02-06")
            date(2024, 2, 6)

            >>> TimeConverter.date_2_date_str(date(2024, 2, 6))
            date(2024, 2, 6)
        """

        if isinstance(date_param, date):
            return date_param

        date_string: str = str(date_param)
        date_result: date = datetime.strptime(date_string, settings.FORMAT.DATE_FORMAT).date()

        return date_result

    @staticmethod
    def datetime_str_2_date(
        datetime_param: DateTimeOrStr,
        to_string: bool = False,
    ) -> DateOrStr:
        """
        日期时间/日期时间字符串 -> 日期

        Args:
            datetime_param: 日期时间/日期时间字符串
            to_string: 是否转换为字符串

        Returns:
            日期

        Examples:
            >>> TimeConverter.datetime_str_2_datetime("2024-02-06 14:11:24")
            date(2024, 2, 6)

            >>> TimeConverter.datetime_str_2_datetime("2024-02-06 14:11:24", to_string=True)
            "2024-02-06"

            >>> TimeConverter.datetime_str_2_datetime(datetime(2024, 2, 6, 14, 11, 24))
            date(2024, 2, 6)

            >>> TimeConverter.datetime_str_2_datetime(datetime(2024, 2, 6, 14, 11, 24), to_string=True)
            "2024-02-06"
        """

        datetime_result: datetime = TimeConverter.datetime_str_2_datetime(datetime_param)
        date_result: date = datetime_result.date()

        if to_string:
            return date_result.strftime(settings.FORMAT.DATE_FORMAT)

        return date_result

    @staticmethod
    def datetime_2_datetime_str(datetime_param: DateTimeOrStr) -> str:
        """
        日期时间/日期时间字符串 -> 日期时间字符串

        Args:
            datetime_param: 日期时间/日期时间字符串

        Returns:
            日期时间字符串

        Examples:
            >>> TimeConverter.datetime_2_datetime_str("2024-02-06 14:11:24")
            "2024-02-06 14:11:24"

            >>> TimeConverter.datetime_2_datetime_str(datetime(2024, 2, 6, 14, 11, 24))
            "2024-02-06 14:11:24"
        """

        if isinstance(datetime_param, datetime):
            date_string = str(datetime_param)[0:19]

        else:
            date_string = str(datetime_param)

        datetime_result: datetime = TimeConverter.datetime_str_2_datetime(date_string)
        datetime_result_string: str = datetime_result.strftime(settings.FORMAT.DATETIME_FORMAT)

        return datetime_result_string

    @staticmethod
    def datetime_2_datetime_full_str(datetime_param: DateTimeOrStr) -> str:
        """
        日期时间/日期时间字符串 -> 日期时间字符串（完整）

        Args:
            datetime_param: 日期时间/日期时间字符串

        Returns:
            日期时间字符串

        Examples:
            >>> TimeConverter.datetime_2_datetime_full_str("2024-02-06 14:11:24")
            "2024-02-06 14:11:24.000"

            >>> TimeConverter.datetime_2_datetime_full_str(datetime(2024, 2, 6, 14, 11, 24))
            "2024-02-06 14:11:24.000"
        """

        if isinstance(datetime_param, datetime):
            date_string = str(datetime_param)[0:19]

        else:
            date_string = str(datetime_param)

        datetime_result: datetime = TimeConverter.datetime_str_2_datetime(date_string)
        datetime_result_string: str = datetime_result.strftime(settings.FORMAT.DATETIME_FULL_FORMAT)[:-3]

        return datetime_result_string

    @staticmethod
    def datetime_str_2_datetime(datetime_param: DateTimeOrStr) -> datetime:
        """
        日期时间/日期时间字符串 -> 日期时间

        Args:
            datetime_param: 日期时间/日期时间字符串

        Returns:
            日期时间

        Examples:
            >>> TimeConverter.datetime_str_2_datetime("2024-02-06 14:11:24")
            datetime(2024, 2, 6, 14, 11, 24)

            >>> TimeConverter.datetime_str_2_datetime(datetime(2024, 2, 6, 14, 11, 24))
            datetime(2024, 2, 6, 14, 11, 24)
        """

        if isinstance(datetime_param, datetime):
            return datetime_param

        datetime_string: str = str(datetime_param)
        datetime_result: datetime = datetime.strptime(datetime_string, settings.FORMAT.DATETIME_FORMAT)

        return datetime_result

    @staticmethod
    def time_str_2_time(time_param: TimeOrStr) -> time:
        """
        时间/时间字符串 -> 时间

        Args:
            time_param: 时间/时间字符串

        Returns:
            time: 时间

        Examples:
            >>> TimeConverter.time_str_2_time("14:28:49")
            time(14, 28, 49)

            >>> TimeConverter.time_str_2_time(time(14, 28, 49))
            time(14, 28, 49)
        """

        if isinstance(time_param, time):
            return time_param

        time_string: str = str(time_param)
        time_result: time = datetime.strptime(time_string, settings.FORMAT.TIME_FORMAT).time()

        return time_result

    @staticmethod
    def time_2_time_str(time_param: TimeOrStr) -> str:
        """
        时间/时间字符串 -> 时间字符串

        Args:
            time_param: 时间/时间字符串

        Returns:
            时间字符串

        Examples:
            >>> TimeConverter.time_2_time_str("14:28:49")
            "14:28:49"

            >>> TimeConverter.time_2_time_str(time(14, 28, 49))
            "14:28:49"
        """

        if isinstance(time_param, time):
            time_string = str(time_param)[0:8]

        else:
            time_string = str(time_param)

        time_result: time = TimeConverter.time_str_2_time(time_string)
        time_result_string: str = time_result.strftime(settings.FORMAT.TIME_FORMAT)

        return time_result_string

    @overload
    @staticmethod
    def get_delta_times(
        time_param: date | str,
        to_string: bool = False,
        years: int = 0,
        months: int = 0,
        days: int = 0,
        hours: int = 0,
        minutes: int = 0,
        seconds: int = 0,
    ) -> date | str:
        ...

    @overload
    @staticmethod
    def get_delta_times(
        time_param: datetime | str,
        to_string: bool = False,
        years: int = 0,
        months: int = 0,
        days: int = 0,
        hours: int = 0,
        minutes: int = 0,
        seconds: int = 0,
    ) -> datetime | str:
        ...

    @overload
    @staticmethod
    def get_delta_times(
        time_param: time | str,
        to_string: bool = False,
        years: int = 0,
        months: int = 0,
        days: int = 0,
        hours: int = 0,
        minutes: int = 0,
        seconds: int = 0,
    ) -> time | str:
        ...

    @staticmethod
    def get_delta_times(
        time_param: DatetimeRelatedType | str,
        to_string: bool = False,
        years: int = 0,
        months: int = 0,
        days: int = 0,
        hours: int = 0,
        minutes: int = 0,
        seconds: int = 0,
    ) -> DatetimeRelatedType | str:
        """
        获取增量的时间

        Args:
            time_param: 时间
            to_string: 是否转换为字符串
            years: 年
            months: 月
            days: 天
            hours: 小时
            minutes: 分钟
            seconds: 秒

        Returns:
            增量的时间

        Raises:
            ValueError 1: 不是合法的时间格式字符串
            ValueError 2: 不是合法的时间格式
        """

        new_time_param: DatetimeRelatedType | str = copy.deepcopy(time_param)
        is_string: bool = isinstance(new_time_param, str)
        is_date: bool = isinstance(new_time_param, date)
        is_time: bool = isinstance(new_time_param, time)
        is_datetime: bool = isinstance(new_time_param, datetime)

        if is_string:
            if re.match(settings.REGEX.DATETIME_REGEX, str(time_param)):
                is_datetime = True
                new_time_param = TimeConverter.datetime_str_2_datetime(new_time_param)

            elif re.match(settings.REGEX.DATE_REGEX, str(time_param)):
                is_date = True
                new_time_param = TimeConverter.date_str_2_date(new_time_param)

            elif re.match(settings.REGEX.TIME_REGEX, str(time_param)):
                is_time = True
                new_time_param = TimeConverter.time_str_2_time(new_time_param)

            else:
                raise ValueError(f"{time_param} 不是合法的时间格式字符串")

        delta_params: DictStrInt = {
            "years": years,
            "months": months,
            "days": days,
            "hours": hours,
            "minutes": minutes,
            "seconds": seconds,
        }

        result: DatetimeRelatedType = new_time_param + relativedelta(**delta_params)

        if to_string:
            if is_date:
                return TimeConverter.date_2_date_str(result)

            elif is_time:
                return TimeConverter.time_2_time_str(result)

            elif is_datetime:
                return TimeConverter.datetime_2_datetime_str(result)

            else:
                raise ValueError(f"{time_param} 不是合法的时间格式")

        return result


if __name__ == "__main__":
    res = TimeConverter.datetime_2_datetime_full_str(datetime.now())
    print(res)

    res_date = TimeConverter.get_delta_times(date(2025, 1, 2))
    res_datetime = TimeConverter.get_delta_times(datetime(2025, 1, 2))
    res_time = TimeConverter.get_delta_times(time(12, 34, 56))
